#include "types.h"
#include "riscv.h"
#include "defs.h"

void test_printf_basic();

void test_printf_edge_cases();

void virtual_memory_init();

void test_map_page();

void test_physical_memory();

void 
main() {
    consoleinit();

    virtual_memory_init();

    // printf("====Basic printf tests:====\n");
    // test_printf_basic();
    // printf("====Edge case printf tests:====\n");
    // test_printf_edge_cases();

    printf("====Testing virtual memory function:====\n");
    test_map_page();
    test_physical_memory();

    while (1)
    {
        /* code */
    }
    
}

void test_printf_basic() {
    printf("Testing integer: %d\n", 42);
    printf("Testing negative: %d\n", -123);
    printf("Testing zero: %d\n", 0);
    printf("Testing hex: 0x%x\n", 0xABC);
    printf("Testing string: %s\n", "Hello");
    printf("Testing char: %c\n", 'X');
    printf("Testing percent: %%\n");
}

void test_printf_edge_cases() {
    printf("INT_MAX: %d\n", 2147483647);
    printf("INT_MIN: %d\n", -2147483648);
    printf("NULL string: %s\n", (char*)0);
    printf("Empty string: %s\n", "");
}

void virtual_memory_init() {
    kinit();
    kvminit();
    kvminithart();
}

void test_physical_memory() {
    // 测试基本分配和释放
    void* page1 = kalloc();
    void* page2 = kalloc();

    if(page1 == page2) {
        printf("kalloc returned the same page twice!\n");
        return;
    }

    if(((uint64)page1 & 0xFFF) != 0) {
        printf("kalloc did not return a page-aligned address!\n");
        return;
    }

    // 测试数据写入
    *(int*)page1 = 0x12345678;
    if(*(int*)page1 != 0x12345678) {
        printf("Memory write/read failed!\n");
        return;
    }

    // 测试释放和重新分配
    kfree(page1);
    void* page3 = kalloc();

    kfree(page2);
    kfree(page3);

    printf("Physical memory allocation and deallocation tests passed.\n");
}

void test_map_page() {
    // 测试基本映射
    pagetable_t pagetable = create_pagetable();

    uint64 va = 0x10000000; // Example virtual address
    uint64 pa = (uint64)kalloc(); // Allocate a physical page

    if(map_page(pagetable, va, pa, PTE_R | PTE_W) != 0) {
        printf("map_page failed!\n");
        return;
    }

    // 测试地址转换
    pte_t *pte = walk(pagetable, va, 1);
    if(PTE2PA(*pte) != pa) {
        printf("walk returned incorrect physical address!\n");
        return;
    }

    //测试权限位设置
    if(!(*pte & PTE_R)) {
        printf("Reading permission bit not set correctly!\n");
        return;
    } 

    if(!(*pte & PTE_W)) {
        printf("Writing permission bit not set correctly!\n");
        return;
    }

    printf("Page mapping tests passed.\n");
}